home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / src890906.arc / AX25CMD.C < prev    next >
C/C++ Source or Header  |  1989-08-19  |  14KB  |  638 lines

  1. #include <stdio.h>
  2. #include "global.h"
  3. #include "mbuf.h"
  4. #include "timer.h"
  5. #include "proc.h"
  6. #include "iface.h"
  7. #include "ax25.h"
  8. #include "lapb.h"
  9. #include "cmdparse.h"
  10. #include "socket.h"
  11. #include "ax25tnc.h"
  12. #include "ax_mbx.h"
  13. #include "session.h"
  14. #include "tty.h"
  15. #include "nr4.h"
  16. #include "commands.h"
  17.  
  18. extern char Notval[];
  19.  
  20. static void ax_in __ARGS((int unused,void *tnc1,void *p));
  21. static int doaxirtt __ARGS((int argc,char *argv[],void *p));
  22. static int doaxkick __ARGS((int argc,char *argv[],void *p));
  23. static int doaxreset __ARGS((int argc,char *argv[],void *p));
  24. static int doaxroute __ARGS((int argc,char *argv[],void *p));
  25. static int doaxstat __ARGS((int argc,char *argv[],void *p));
  26. static int doaxwindow __ARGS((int argc,char *argv[],void *p));
  27. static int dodigipeat __ARGS((int argc,char *argv[],void *p));
  28. static int domaxframe __ARGS((int argc,char *argv[],void *p));
  29. static int domycall __ARGS((int argc,char *argv[],void *p));
  30. static int don2 __ARGS((int argc,char *argv[],void *p));
  31. static int dopaclen __ARGS((int argc,char *argv[],void *p));
  32. static int dopthresh __ARGS((int argc,char *argv[],void *p));
  33. static int dot3 __ARGS((int argc,char *argv[],void *p));
  34. static int doversion __ARGS((int argc,char *argv[],void *p));
  35.  
  36. char *Ax25states[] = {
  37.     "Disconnected",
  38.     "Listening",
  39.     "Conn pending",
  40.     "Disc pending",
  41.     "Connected",
  42.     "Recovery",
  43.     "Frame Reject",
  44. };
  45.  
  46. /* Ascii explanations for the disconnect reasons listed in lapb.h under
  47.  * "reason" in ax25_cb
  48.  */
  49. char *Axreasons[] = {
  50.     "Normal",
  51.     "DM received",
  52.     "Timeout"
  53. };
  54.  
  55. static struct cmds Axcmds[] = {
  56.     "digipeat",    dodigipeat,    0, 0, NULLCHAR,
  57.     "irtt",        doaxirtt,    0, 0, NULLCHAR,
  58.     "kick",        doaxkick,    0, 2, "ax25 kick <axcb>",
  59.     "maxframe",    domaxframe,    0, 0, NULLCHAR,
  60.     "mycall",    domycall,    0, 0, NULLCHAR,
  61.     "paclen",    dopaclen,    0, 0, NULLCHAR,
  62.     "pthresh",    dopthresh,    0, 0, NULLCHAR,
  63.     "reset",    doaxreset,    0, 2, "ax25 reset <axcb>",
  64.     "retry",    don2,        0, 0, NULLCHAR,
  65.     "route",    doaxroute,    0, 0, NULLCHAR,
  66.     "status",    doaxstat,    0, 0, NULLCHAR,
  67.     "t3",        dot3,        0, 0, NULLCHAR,
  68.     "version",    doversion,    0, 0, NULLCHAR,
  69.     "window",    doaxwindow,    0, 0, NULLCHAR,
  70.     NULLCHAR,
  71. };
  72. /* Multiplexer for top-level ax25 command */
  73. int
  74. doax25(argc,argv,p)
  75. int argc;
  76. char *argv[];
  77. void *p;
  78. {
  79.     return subcmd(Axcmds,argc,argv,p);
  80. }
  81.  
  82. static
  83. doaxreset(argc,argv,p)
  84. int argc;
  85. char *argv[];
  86. void *p;
  87. {
  88.     struct ax25_cb *axp;
  89.  
  90.     axp = (struct ax25_cb *)ltop(htol(argv[1]));
  91.     if(!ax25val(axp)){
  92.         printf(Notval);
  93.         return 1;
  94.     }
  95.     reset_ax25(axp);
  96.     return 0;
  97. }
  98.  
  99. /* Display AX.25 link level control blocks */
  100. static
  101. doaxstat(argc,argv,p)
  102. int argc;
  103. char *argv[];
  104. void *p;
  105. {
  106.     register int i;
  107.     register struct ax25_cb *axp;
  108.     char tmp[10];
  109.  
  110.     if(argc < 2){
  111.         printf("    &AXB Snd-Q   Rcv-Q   Remote    State\n");
  112.         for(i=0;i<NHASH;i++){
  113.             for(axp = Ax25_cb[i];axp != NULLAX25; axp = axp->next){
  114.                 pax25(tmp,&axp->remote);
  115.                 printf("%8lx %-8d%-8d%-10s%s\n",
  116.                     ptol(axp),
  117.                     len_q(axp->txq),len_mbuf(axp->rxq),
  118.                     tmp,Ax25states[axp->state]);
  119.             }
  120.         }
  121.         return 0;
  122.     }
  123.     axp = (struct ax25_cb *)ltop(htol(argv[1]));
  124.     if(!ax25val(axp)){
  125.         printf(Notval);
  126.         return 1;
  127.     }
  128.     st_ax25(axp);
  129.     return 0;
  130. }
  131. /* Dump one control block */
  132. void
  133. st_ax25(axp)
  134. register struct ax25_cb *axp;
  135. {
  136.     char tmp[10];
  137.  
  138.     if(axp == NULLAX25)
  139.         return;
  140.     printf("    &AXB Remote   RB V(S) V(R) Unack P Retry State\n");
  141.     pax25(tmp,&axp->remote);
  142.     printf("%8lx %-9s",ptol(axp),tmp);
  143.     putchar(axp->flags.rejsent ? 'R' : ' ');
  144.     putchar(axp->flags.remotebusy ? 'B' : ' ');
  145.     printf(" %4d %4d",axp->vs,axp->vr);
  146.     printf(" %02u/%02u %u",axp->unack,axp->maxframe,axp->proto);
  147.     printf(" %02u/%02u",axp->retries,axp->n2);
  148.     printf(" %s\n",Ax25states[axp->state]);
  149.  
  150.     printf("SRT = %lu ",axp->srt * MSPTICK);
  151.     printf("T1: ");
  152.     if(run_timer(&axp->t1))
  153.         printf("%lu",read_timer(&axp->t1) * MSPTICK);
  154.     else
  155.         printf("stop");
  156.     printf("/%lu ms; ",dur_timer(&axp->t1) * MSPTICK);
  157.  
  158.     printf("T3: ");
  159.     if(run_timer(&axp->t3))
  160.         printf("%lu",read_timer(&axp->t3) * MSPTICK);
  161.     else
  162.         printf("stop");
  163.     printf("/%lu ms\n",dur_timer(&axp->t3) * MSPTICK);
  164.  
  165. }
  166.  
  167. /* Display or change our AX.25 address */
  168. static
  169. domycall(argc,argv,p)
  170. int argc;
  171. char *argv[];
  172. void *p;
  173. {
  174.     char buf[15];
  175.  
  176.     if(argc < 2){
  177.         pax25(buf,&Mycall);
  178.         printf("%s\n",buf);
  179.         return 0;
  180.     }
  181.     if(setcall(&Mycall,argv[1]) == -1)
  182.         return -1;
  183.     Mycall.ssid |= E;
  184.     return 0;
  185. }
  186.  
  187. /* Control AX.25 digipeating */
  188. static
  189. dodigipeat(argc,argv,p)
  190. int argc;
  191. char *argv[];
  192. void *p;
  193. {
  194.     return setbool(&Digipeat,"Digipeat",argc,argv);
  195. }
  196. static
  197. doversion(argc,argv,p)
  198. int argc;
  199. char *argv[];
  200. void *p;
  201. {
  202.     return setshort(&Axversion,"AX25 version",argc,argv);
  203. }
  204.  
  205. static
  206. doaxirtt(argc,argv,p)
  207. int argc;
  208. char *argv[];
  209. void *p;
  210. {
  211.     return setlong(&Axirtt,"Initial RTT (ms)",argc,argv);
  212. }
  213.  
  214. /* Set idle timer */
  215. static
  216. dot3(argc,argv,p)
  217. int argc;
  218. char *argv[];
  219. void *p;
  220. {
  221.     return setlong(&T3init,"Idle poll timer (ms)",argc,argv);
  222. }
  223.  
  224. /* Set retry limit count */
  225. static
  226. don2(argc,argv,p)
  227. int argc;
  228. char *argv[];
  229. void *p;
  230. {
  231.     return setshort(&N2,"Retry limit",argc,argv);
  232. }
  233. /* Force a retransmission */
  234. static
  235. doaxkick(argc,argv,p)
  236. int argc;
  237. char *argv[];
  238. void *p;
  239. {
  240.     struct ax25_cb *axp;
  241.  
  242.     axp = (struct ax25_cb *)ltop(htol(argv[1]));
  243.     if(!ax25val(axp)){
  244.         printf(Notval);
  245.         return 1;
  246.     }
  247.     kick_ax25(axp);
  248.     return 0;
  249. }
  250. /* Set maximum number of frames that will be allowed in flight */
  251. static
  252. domaxframe(argc,argv,p)
  253. int argc;
  254. char *argv[];
  255. void *p;
  256. {
  257.     return setshort(&Maxframe,"Window size (frames)",argc,argv);
  258. }
  259.  
  260. /* Set maximum length of I-frame data field */
  261. static
  262. dopaclen(argc,argv,p)
  263. int argc;
  264. char *argv[];
  265. void *p;
  266. {
  267.     return setshort(&Paclen,"Max frame length (bytes)",argc,argv);
  268. }
  269. /* Set size of I-frame above which polls will be sent after a timeout */
  270. static
  271. dopthresh(argc,argv,p)
  272. int argc;
  273. char *argv[];
  274. void *p;
  275. {
  276.     return setshort(&Pthresh,"Poll threshold (bytes)",argc,argv);
  277. }
  278.  
  279. /* Set high water mark on receive queue that triggers RNR */
  280. static
  281. doaxwindow(argc,argv,p)
  282. int argc;
  283. char *argv[];
  284. void *p;
  285. {
  286.     return setshort(&Axwindow,"AX25 receive window (bytes)",argc,argv);
  287. }
  288. /* End of ax25 subcommands */
  289.  
  290. /* Initiate interactive AX.25 connect to remote station */
  291. int
  292. doconnect(argc,argv,p)
  293. int argc;
  294. char *argv[];
  295. void *p;
  296. {
  297.     struct sockaddr_ax fsocket;
  298.     struct session *sp;
  299.  
  300.     /* Allocate a session descriptor */
  301.     if((sp = newsession(argv[2],AX25TNC)) == NULLSESSION){
  302.         printf("Too many sessions\n");
  303.         freeargs(argc,argv);
  304.         return 1;
  305.     }
  306.     if((sp->s = socket(AF_AX25,SOCK_STREAM,0)) == -1){
  307.         freesession(sp);
  308.         printf("Can't create socket\n");
  309.         freeargs(argc,argv);
  310.         return 1;
  311.     }
  312.     fsocket.sax_family = AF_AX25;
  313.     setcall(&fsocket.ax25_addr,argv[2]);
  314.     strncpy(fsocket.iface,argv[1],ILEN);
  315.     freeargs(argc,argv);
  316.     printf("Trying %s...\n",psocket((struct sockaddr *)&fsocket));
  317.     return axnrconnect(sp, (char *)&fsocket, sizeof(struct sockaddr_ax));
  318. }
  319.  
  320. /* Generic interactive connect routine, used by both AX.25 and NET/ROM */
  321. int
  322. axnrconnect(sp, fsocket, len)
  323. struct session *sp;
  324. char *fsocket;
  325. int len;
  326. {
  327.     struct mbuf *bp;
  328.     char *cp;
  329.  
  330.     Current = sp;
  331.     Mode = CONV_MODE;
  332.     sp->cb.ax25 = (struct ax25tnc *)calloc(1,sizeof(struct ax25tnc));
  333.     sp->cb.ax25->session = sp;
  334.     sp->cb.ax25->output = Curproc;
  335.     if(connect(sp->s,fsocket,len) == -1){
  336.         printf("%s session %u failed: %s errno %d\n",
  337.                Sestypes[sp->type],(unsigned)(sp-Sessions),
  338.                sockerr(sp->s),errno);
  339.         close_s(sp->s);
  340.         free((char *)sp->cb.ax25);
  341.         freesession(sp);
  342.         return 1;
  343.     }
  344.     printf("%s session %u connected to %s\n",Sestypes[sp->type],
  345.         (unsigned)(sp-Sessions),sp->name);
  346.     sp->cb.ax25->output = Curproc;
  347.     sp->cb.ax25->input = newproc("ax_in",1024,ax_in,0,sp->cb.ax25,NULL);
  348.     for(;;){
  349.         while(sp->input == NULLBUF)
  350.             pwait(&sp->input);
  351.  
  352.         bp = dequeue(&sp->input);
  353.  
  354.         /* If we're recording, record it */
  355.         if(sp->record != NULLFILE)
  356.             write_p(sp->record,bp);
  357.  
  358.         /* Get rid of the trailing newline */
  359.         if((cp = strchr(bp->data,'\n')) != NULLCHAR){
  360.             *cp = '\0';
  361.             bp->cnt--;
  362.         }
  363.         if(send_mbuf(sp->s,bp,0,NULLCHAR,0) == -1)
  364.             break;
  365.     }
  366.     killproc(sp->cb.ax25->input);
  367.     close_s(sp->s);
  368.     free(sp->cb.ax25);
  369.     freesession(sp);
  370.     return 0;
  371. }
  372. /* Display and modify AX.25 routing table */
  373. static int
  374. doaxroute(argc,argv,p)
  375. int argc;
  376. char *argv[];
  377. void *p;
  378. {
  379.     char buf[30];
  380.     int i,j,ndigis;
  381.     register struct ax_route *axr;
  382.     struct ax25_addr target,digis[MAXDIGIS];
  383.  
  384.     if(argc < 2){
  385.         printf("Target    Type   Digipeaters\n");
  386.         for(i=0;i<NAXROUTE;i++){
  387.             for(axr = Ax_routes[i];axr != NULLAXR;axr = axr->next){
  388.                 pax25(buf,&axr->target);
  389.                 printf("%-10s%-6s",buf,
  390.                  axr->type == AX_LOCAL ? "Local":"Auto");
  391.                 for(j=0;j<axr->ndigis;j++){
  392.                     pax25(buf,&axr->digis[j]);
  393.                     printf(" %s",buf);
  394.                 }
  395.                 printf("\n");
  396.             }
  397.         }
  398.         return 0;
  399.     }
  400.     if(argc < 3){
  401.         printf("Usage: ax25 route add <target> [digis...]\n");
  402.         printf("       ax25 route drop <target>\n");
  403.         return 1;
  404.     }
  405.     if(setcall(&target,argv[2]) == -1){
  406.         printf("Bad target %s\n",argv[2]);
  407.         return 1;
  408.     }
  409.     switch(argv[1][0]){
  410.     case 'a':    /* Add route */
  411.         if(argc < 3){
  412.             printf("Usage: ax25 route add <target> [digis...]\n");
  413.             return 1;
  414.         }
  415.         ndigis = argc - 3;
  416.         for(i=0;i<ndigis;i++){
  417.             if(setcall(&digis[i],argv[i+3]) == -1){
  418.                 printf("Bad digipeater %s\n",argv[i+3]);
  419.                 return 1;
  420.             }
  421.         }
  422.         if(ax_add(&target,AX_LOCAL,&digis[0],ndigis) == NULLAXR){
  423.             printf("Failed\n");
  424.             return 1;
  425.         }
  426.         break;
  427.     case 'd':    /* Drop route */
  428.         if(ax_drop(&target) == -1){
  429.             printf("Not in table\n");
  430.             return 1;
  431.         }
  432.         break;
  433.     default:
  434.         printf("Unknown command %s\n",argv[1]);
  435.         return 1;
  436.     }
  437.     return 0;
  438. }
  439. /* Upload process for both AX.25 and NET/ROM sessions */
  440. void
  441. ax_upload(unused,sp1,p)
  442. int unused;
  443. void *sp1;
  444. void *p;
  445. {
  446.     struct mbuf *bp;
  447.     char *cp;
  448.     int c,bufsize;
  449.     struct session *sp;
  450.  
  451.     sp = (struct session *)sp1;
  452.     /* NET/ROM is a sequenced packet protocol, so we have to make sure
  453.        that the length of each packet is within legal limits */
  454.     if (sp->type == NRSESSION)
  455.         bufsize = NR4MAXINFO;
  456.     else
  457.         bufsize = BUFSIZ;
  458.     for(;;){
  459.         bp = alloc_mbuf(bufsize);
  460.         cp = bp->data;
  461.         while(bp->cnt < bufsize){
  462.             if((c = getc(sp->upload)) == EOF)
  463.                 break;
  464.             if(c == '\r')
  465.                 continue;
  466.             if(c == '\n')
  467.                 c = '\r';
  468.             *cp++ = c;
  469.             bp->cnt++;
  470.         }
  471.         if(bp->cnt == 0){
  472.             free_p(bp);
  473.             break;
  474.         } else if(send_mbuf(sp->s,bp,0,NULLCHAR,0) == -1)
  475.             break;
  476.     }
  477.     fclose(sp->upload);
  478.     sp->upload = NULLFILE;
  479.     free(sp->ufile);
  480.     sp->ufile = NULLCHAR;
  481.     sp->cb.ax25->upload = NULLPROC;
  482. }
  483. /* AX.25 TNC receive process, used by both AX.25 and NET/ROM sessions */
  484. static void
  485. ax_in(unused,tnc1,p)
  486. int unused;
  487. void *tnc1;
  488. void *p;
  489. {
  490.     char c;
  491.     struct session *sp;
  492.     char *cp;
  493.     struct mbuf *bp;
  494.     int s;
  495.     struct ax25tnc *tnc;
  496.  
  497.     tnc = (struct ax25tnc *)tnc1;
  498.     sp = tnc->session;
  499.     s = sp->s;
  500.  
  501.     for(;;){
  502.         if(recv_mbuf(s,&bp,0,0,NULLCHAR,0) == -1)
  503.             break;
  504.         while(pullup(&bp,&c,1) == 1){
  505.             /* Suspend output if we're not current */
  506.             while(Current != sp || Mode != CONV_MODE)
  507.                 pwait(sp);
  508.  
  509.             putchar(c);
  510.             if(c == '\r')
  511.                 putchar('\n');
  512.  
  513.             if(sp->record != NULLFILE){
  514. #ifdef UNIX
  515.                 if(c != '\r')
  516. #endif                
  517.                 putc(c,sp->record);
  518.                 if(c == '\r')
  519.                     putc('\n',sp->record);
  520.             }
  521.         }
  522.     }
  523.     /* Close seen from remote host */
  524.     cp = sockerr(s);
  525.     printf("%s session %u closed: %s\n", Sestypes[sp->type],
  526.            (unsigned)(sp - Sessions),
  527.            cp != NULLCHAR ? cp : "EOF");
  528.     close_s(s);
  529.     tnc->input = NULLPROC;
  530.     killproc(tnc->output);
  531.     free((char *)tnc);
  532.     freesession(sp);
  533. }
  534.  
  535. int
  536. ax25start(argc,argv,p)
  537. int argc;
  538. char *argv[];
  539. void *p;
  540. {
  541.     int s;
  542.     char buf[80];
  543.  
  544.     freeargs(argc,argv);    /* Args are not used */
  545.     if (Axi_sock != -1)
  546.         return 0;
  547.  
  548.     psignal(Curproc,0);    /* Don't keep the parser waiting */
  549.     chname(Curproc,"AX25 listener");
  550.     Axi_sock = socket(AF_AX25,SOCK_STREAM,0);
  551.     /* bind() is done automatically */
  552.     if(listen(Axi_sock,1) == -1){
  553.         close_s(Axi_sock);
  554.         return -1;
  555.     }
  556.     for(;;){
  557.         if((s = accept(Axi_sock,NULLCHAR,NULLINT)) == -1)
  558.             break;    /* Service is shutting down */
  559.  
  560.         if(Ax25mbox){
  561.             /* Eat the line that triggered the connection
  562.              * and then start the mailbox
  563.              */
  564.             recvline(s,buf,80); 
  565.             newproc("mbox",2048,mbx_incom,s,(void *)AX25TNC,NULL);
  566.         } else
  567.             newproc("in_ax25",2048,axnrhandle,s,(void *)AX25TNC,NULL);
  568.     }
  569.     close_s(Axi_sock);
  570.     Axi_sock = -1;
  571.     return 0;
  572. }
  573. int
  574. ax250(argc,argv,p)
  575. int argc;
  576. char *argv[];
  577. void *p;
  578. {
  579.     close_s(Axi_sock);
  580.     Axi_sock = -1;
  581.     return 0;
  582. }
  583. /* This function handles both incoming AX25 and NETROM sessions */
  584. void
  585. axnrhandle(s,t,p)
  586. int s;
  587. void *t;
  588. void *p;
  589. {
  590.     int type;
  591.     struct session *sp;
  592.     char buf[20], *cp;
  593.     struct mbuf *bp;
  594.     char addr[MAXSOCKSIZE];
  595.     int len = MAXSOCKSIZE;
  596.  
  597.     type = (int)t;
  598.     sockowner(s,Curproc);    /* We own it now */
  599.     sprintf(buf,"open %s",Sestypes[type]);
  600.     log(s,buf);
  601.         /* Allocate a session descriptor */
  602.     if((sp = newsession(NULLCHAR,type)) == NULLSESSION){
  603.         usprintf(s,"Too many sessions\n");
  604.         close_s(s);
  605.     }
  606.     getpeername(s,addr,&len);
  607.     printf("\007Incoming %s session %u from %s\007\n",Sestypes[type],
  608.      (unsigned)(sp - Sessions),psocket(addr));
  609.     sp->cb.ax25 = (struct ax25tnc *)calloc(1,sizeof(struct ax25tnc));
  610.     sp->cb.ax25->session = sp;
  611.     sp->cb.ax25->output = Curproc;
  612.     sp->s = s;
  613.     sp->ttymode = TTY_EDIT|TTY_ECHO;
  614.     sp->cb.ax25->input = newproc("ax_in",1024,ax_in,0,sp->cb.ax25,NULL);
  615.     for(;;){
  616.         while(sp->input == NULLBUF)
  617.             pwait(&sp->input);
  618.  
  619.         bp = dequeue(&sp->input);
  620.  
  621.         /* If we're recording, record it */
  622.         if(sp->record != NULLFILE)
  623.             write_p(sp->record,bp);
  624.  
  625.         /* Get rid of the trailing newline */
  626.         if((cp = strchr(bp->data,'\n')) != NULLCHAR){
  627.             *cp = '\0';
  628.             bp->cnt--;
  629.         }
  630.         if(send_mbuf(s,bp,0,NULLCHAR,0) == -1)
  631.             break;
  632.     }
  633.     killproc(sp->cb.ax25->input);
  634.     close_s(s);
  635.     free((char *)sp->cb.ax25);
  636.     freesession(sp);
  637. }
  638.